AWS LambdaのカスタムランタイムでC++を動かしてみた #reinvent
はじめに
福岡のyoshihitohです。先日のre:Invent 2018で発表されたAWS Lambdaのカスタムランタイムが発表されました。
【アップデート】 もう言語で悩まない!AWS LambdaでCustom Runtimeが利用できるようになりました! #reinvent
今回はこれを使ってC++を動かしてみます。
このエントリは AWS Lambda Custom Runtimes芸人 Advent Calendar 2018 2日目の記事です。
検証環境
- macOS: 10.13.6
- Command Line Tools for Xcode: 10.0.0.0.1.1535735448
- CMake: 3.9.0
- Docker: 18.09.0, build 4d60db4
試すこと
まずは動くことを確認するため、ペイロードをエコー表示するだけの簡単なものを試してみます。
環境構築
カスタムランタイムを使う場合はアプリケーションをzipファイルでアップロードします。 aws-lambda-cpp を利用すると、zipファイルにアーカイブするMakefileも自動生成できるのでこれを利用します。
また、Linux環境用のバイナリが必要なのでDockerを使ってビルドします。
参考
- Introducing the C++ Lambda Runtime | AWS Compute Blog
- aws-lambda-cpp/examples/s3 at master · awslabs/aws-lambda-cpp · GitHub
Lambdaアプリケーションのプロジェクトを作る
サンプルを参考にアプリケーションのメイン処理を作成します。
#include <aws/lambda-runtime/runtime.h> using namespace aws::lambda_runtime; static invocation_response my_handler(invocation_request const& req) { return invocation_response::success("Echo: " \+ req.payload, "text/plain"); } int main() { run\_handler(my\_handler); return 0; }
次にCMakeプロジェクトを作成します。
cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 14) project(cpp-lambda LANGUAGES CXX) find_package(aws-lambda-runtime) # (A) find_package(AWSSDK COMPONENTS s3) # (B) add_executable(${PROJECT_NAME} "main.cpp") target_link_libraries(${PROJECT_NAME} PRIVATE AWS::aws-lambda-runtime ${AWSSDK_LINK_LIBRARIES}) # (C) target_compile_features(${PROJECT_NAME} PRIVATE "cxx_std_14") target_compile_options(${PROJECT_NAME} PRIVATE "-Wall" "-Wextra") # this line creates a target that packages your binary and zips it up aws_lambda_package_target(${PROJECT_NAME}) # (D)
- (A): AWS LambdaのC++用ランタイムパッケージを利用するための指定です
- (B): AWS SDK for C++パッケージを利用するための指定です
- (C): C++用ランタイムとAWS SDKをリンクする指定です
- (D): アップロードするzipファイルを作成するための指定です
Dockerファイル作成
次にC++ビルド環境を準備します。
FROM alpine:latest # (1) ビルド環境・依存ライブラリをインストール RUN apk update && apk add cmake make git g++ bash curl-dev zlib-dev openssl-dev zip # (2) C++用カスタムランタイムをビルド&インストール WORKDIR /opt/src RUN mkdir -p external && \ cd external && \ git clone https://github.com/awslabs/aws-lambda-cpp-runtime.git && \ mkdir -p aws-lambda-cpp-runtime/build && \ cd aws-lambda-cpp-runtime/build && \ cmake .. -DCMAKE_BUILD_TYPE=Release \ -DBUILD_SHARED_LIBS=OFF \ -DCMAKE_INSTALL_PREFIX=/opt/lambda-install && \ make -j$(nproc) && \ make install # (3) アプリケーションをビルド&ZIPファイル化 COPY . /opt/src RUN mkdir build && \ cd build && \ cmake -G "Unix Makefiles" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_PREFIX_PATH="/opt/lambda-install;/opt/awssdk-install" \ .. && \ make && make aws-lambda-package-cpp-lambda CMD ["ls", "-lah"]
本番環境で動作させる場合は必ず -DCMAKE_BUILD_TYPE=Release
を指定してリリース版でビルドしましょう。 (デバッグ版だとパフォーマンスが著しく低下するため)
ここまででビルド設定は完了です。ビルドできるか試してみます。
$ docker image build -t lambda-cpp-runtime . Sending build context to Docker daemon 454.3MB Step 1/9 : FROM alpine:latest ---> 3fd9065eaf02 Step 2/9 : RUN apk update && apk add cmake make git g++ bash curl-dev zlib-dev openssl-dev zip ---> Using cache ---> 394d8401b765 Step 3/9 : WORKDIR /opt/src ---> Using cache ---> d5cfb9056db9 Step 4/9 : RUN mkdir -p external && cd external && git clone https://github.com/awslabs/aws-lambda-cpp-runtime.git && mkdir -p aws-lambda-cpp-runtime/build && cd aws-lambda-cpp-runtime/build && cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=/opt/lambda-install && make -j$(nproc) && make install ---> Using cache ---> 97daa8d06318 Step 5/9 : RUN cd external && git clone https://github.com/aws/aws-sdk-cpp.git && mkdir -p aws-sdk-cpp/build && cd aws-sdk-cpp/build && cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_ONLY="s3" -DCUSTOM_MEMORY_MANAGEMENT=OFF -DBUILD_SHARED_LIBS=OFF -DENABLE_UNITY_BUILD=ON -DCMAKE_INSTALL_PREFIX=/opt/awssdk-install && make -j$(nproc) && make install ---> Using cache ---> 591d2de4cadb Step 6/9 : RUN cd external && git clone https://github.com/mapbox/gzip-hpp ---> Using cache ---> f7a9929dd8f2 Step 7/9 : COPY . /opt/src ---> caf6aa62d0d8 Step 8/9 : RUN mkdir build && cd build && cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="/opt/lambda-install;/opt/awssdk-install" .. && make && make aws-lambda-package-cpp-lambda ---> Running in 4ee7d3ec7d0b -- The CXX compiler identification is GNU 6.4.0 -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- TARGET_ARCH not specified; inferring host OS to be platform compilation target -- Building AWS libraries as static objects -- Generating linux build config -- Building project version: 1.7.11 -- Found AWS SDK for C++, Version: 1.7.11, Install Root:/opt/awssdk-install, Platform Prefix:, Platform Dependent Libraries: pthread;crypto;ssl;z;curl -- Components specified for AWSSDK: s3 -- Try finding aws-cpp-sdk-core -- Found aws-cpp-sdk-core -- Try finding aws-cpp-sdk-s3 -- Found aws-cpp-sdk-s3 -- Configuring done -- Generating done -- Build files have been written to: /opt/src/build Scanning dependencies of target cpp-lambda [ 50%] Building CXX object CMakeFiles/cpp-lambda.dir/main.cpp.o [100%] Linking CXX executable cpp-lambda /usr/lib/gcc/x86_64-alpine-linux-musl/6.4.0/../../../../x86_64-alpine-linux-musl/bin/ld: warning: libssl.so.44, needed by /usr/lib/gcc/x86_64-alpine-linux-musl/6.4.0/../../../../lib/libcurl.so, may conflict with libssl.so.1.0.0 /usr/lib/libssl.so: warning: warning: EVP_EncryptFinal is often misused, please use EVP_EncryptFinal_ex and EVP_CIPHER_CTX_cleanup /usr/lib/libssl.so: warning: warning: EVP_DecryptFinal is often misused, please use EVP_DecryptFinal_ex and EVP_CIPHER_CTX_cleanup /usr/lib/gcc/x86_64-alpine-linux-musl/6.4.0/../../../../lib/libcrypto.so: warning: warning: EVP_CipherFinal is often misused, please use EVP_CipherFinal_ex and EVP_CIPHER_CTX_cleanup [100%] Built target cpp-lambda [100%] Built target cpp-lambda Scanning dependencies of target aws-lambda-package-cpp-lambda adding: bin/ (stored 0%) adding: bin/cpp-lambda (deflated 62%) adding: bootstrap (deflated 24%) adding: lib/ (stored 0%) adding: lib/libgcc_s.so.1 (deflated 54%) adding: lib/ld-musl-x86_64.so.1 (deflated 37%) adding: lib/libssl.so.44 (deflated 60%) adding: lib/libssl.so.1.0.0 (deflated 59%) adding: lib/libssh2.so.1 (deflated 57%) adding: lib/libz.so.1 (deflated 46%) adding: lib/libcrypto.so.42 (deflated 58%) adding: lib/libstdc++.so.6 (deflated 71%) adding: lib/libcurl.so.4 (deflated 52%) adding: lib/libcrypto.so.1.0.0 (deflated 55%) Created /opt/src/build/cpp-lambda.zip [100%] Built target aws-lambda-package-cpp-lambda Removing intermediate container 4ee7d3ec7d0b ---> b42cfabaab8a Step 9/9 : CMD ["ls", "-lah"] ---> Running in 8efa8fcbedf4 Removing intermediate container 8efa8fcbedf4 ---> 16f5ded7b5b4 Successfully built 16f5ded7b5b4 Successfully tagged blog/cpp-runtime:latest
ビルドできましたね!
最後にコンテナを起動してAWS Lambdaで使うzipファイルを取得します。
$ docker container run --name lambda-cpp lambda-cpp-runtime $ docker container cp lambda-cpp:/opt/src/build/cpp-lambda.zip .
ファンクションを作成
作成手順は下記の記事の「Lambdaファンクション作成」と同様です。
ファンクションを動かす
下記データを流してファンクションを動かしてみます。
{ "key1": "value1", "key2": "value2", "key3": "value3" }
ちゃんと動きましたね!
おわりに
今回はカスタムランタイムを使ってC++のアプリケーションを動かしてみました。カスタムランタイムで好きな言語が使えるようになったのは非常にありがたいですね!
次回はS3やDynamoDBといったAWSのサービスと連動させてみたいと思います!